<?php
// -------------------------------------------------------------------------------------------------------------------
class ccdsImageCache
{
    private $config;

    function __construct( )
    {
        $config=ccdsConfig::getInstance();
        $this->config=$config;

        $this->engine=$config->get( 'RESIZE_ENGINE' );
        $this->tools = ccdsTools::getInstance();
    }

    static function &getInstance( )
    {
        static $obj;

        if ( !$obj )
        {
            $obj=new ccdsImageCache();
        }
        return $obj;
    }

    function image_info( $img_src )
    {
    		if (!is_file($img_src)) return;
        $engine=$this->config->get( 'RESIZE_ENGINE' );

        switch ( $engine )
            {
            case 'IMAGICK_PECL':
                $img_attrb=array();
                $handle=imagick_readimage( $img_src );

                if ( imagick_iserror( $handle ) )
                {
                    $reason=imagick_failedreason( $handle );
                    $description=imagick_faileddescription( $handle );
                    print "handle failed!<BR>\nReason: $reason<BR>\nDescription: $description<BR>\n";
                }
                else
                {
                    $img_attrb['width']=imagick_getwidth( $handle );
                    $img_attrb['height']=imagick_getheight( $handle );
                }
                break;

            case 'IMAGICK_PECL2':

                $image=new Imagick( $img_src );
                $img_attrb=$image->getImageGeometry();

                $image->destroy();
                unset( $image );

                break;

            case 'IMAGICK_SHELL':
                ob_start();
                $out=system( "convert " . $img_src . " info:-" );
                ob_get_clean();
                list( $name, $type, $size )=split( " ", $out );
                list( $x, $y )=split( "x", $size );

                $img_attrb['width']=$x;
                $img_attrb['height']=$y;
                break;
            case 'MAGICKWAND':
							$resource = NewMagickWand();
							MagickReadImage( $resource, $img_src );
							$img_attrb['width']=MagickGetImageWidth($resource);
							$img_attrb['height'] = MagickGetImageHeight($resource);	
							
	           break;

            case 'GD':
							$resource = imagecreatefromjpeg($img_src);
							$img_attrb['width']=imagesx($resource);
							$img_attrb['height'] = imagesy($resource);	
							
	           break;

	          default:
	          	$img_attrb = getimagesize($img_src);
	          
	          break;
           }

        return $img_attrb;
    }

// -------------------------------------------------------------------------------------------------------------------

   function image_quickinfo( $img_src )
    {
    		if (!is_file($img_src)) return;
       
       
       	$size = getimagesize($img_src);
       	$img_attrb = array('width' => $size[0],'height' => $size[1]);
				
        return $img_attrb;
    }
    
    
// -------------------------------------------------------------------------------------------------------------------
    
		function getProportionalSize($orig_x, $orig_y, $max_x, $max_y){
		    
		    $new_x = $orig_x;
		    $new_y = $orig_y;
		
				$max_ratio = $max_x / $max_y;
				$orig_ratio =  $orig_x / $orig_y;
		
		    $per_x = $orig_x / $max_x;
		    $per_y = $orig_y / $max_y;
		    if ($max_ratio > $orig_ratio) {
		      $new_x = floor($orig_x / $per_y);
		      $new_y = $max_y;
		    }
		    else {
		      $new_y = floor($orig_y / $per_x);
		      $new_x = $max_x;
		    }
		   return array($new_x,$new_y);
		}

// -------------------------------------------------------------------------------------------------------------------

    function img_cache_resize( $img_src, $img_width, $img_height, $img_stretch=0, $img_quality=80,$img_type=false )
    {
    		if (!is_file($img_src)) return;

        $matches=array();
        preg_match("/\.([^\.]*?)$/",$img_src,$matches);
        $img_end = strtolower($matches[1]);
        
        
				
        if ( $img_end != 'jpg' && $img_end != 'jpeg' && $img_end != 'gif' && $img_end != 'png' )
        {
            $img_end='jpg';
        }
        
        $file_name = MD5( $img_src );
        
        $dir = substr($file_name,0,2);
        $dir_path = $this->config->get( 'IMAGE_CACHE_ROOT' ) .$dir;
        if (!is_dir($dir_path)) {
        	$this->tools->mkdir($dir_path);
        }

        $img_destfile=
              $file_name . "." . $img_width . "x" . $img_height . "x" . $img_stretch;
         
        if (false != $img_type) {
        	$img_destfile.="x".$img_type;
        } 
//        $img_destfile.= rand(0,1000);
        $img_destfile .= ".". $img_end;
        $img_destination=$dir_path. '/'.$img_destfile;
        $create_new=false;

        if ( file_exists( $img_destination ) )
        {
            $dest_stat=stat( $img_destination );
            $source_stat=stat( $img_src );

            if ( $dest_stat['mtime'] < $source_stat['mtime'] )
            {
                $create_new=true;
                unlink( $img_destination );
            }
        }
        else
        {
            $create_new=true;
        }

        if ( $create_new )
        {
            switch ( $this->engine )
                {
                case 'IMAGICK_PECL':
                    $handle=imagick_readimage( $img_src );

                    if ( imagick_iserror( $handle ) )
                    {
                        $reason=imagick_failedreason( $handle );
                        $description=imagick_faileddescription( $handle );
                        print "handle failed!<BR>\nReason: $reason<BR>\nDescription: $description<BR>\n";
                    }
                    $img_attrb['width']=imagick_getwidth( $handle );
                    $img_attrb['height']=imagick_getheight( $handle );

                    if ( $img_stretch == 0 )
                    {
                        if ( ( $img_attrb['width'] <= $img_width ) AND ( $img_attrb['height'] <= $img_height ) )
                        {
                            $img_width=$img_attrb['width'];
                            $img_height=$img_attrb['height'];
                        }
                    }

                    imagick_resize( $handle, $img_width, $img_height, IMAGICK_FILTER_HERMITE, .8 );
                    imagick_setcompressionquality( $handle, $img_quality );

                    if ( !imagick_writeimage( $handle, $img_destination ) )
                    {
                        $reason=imagick_failedreason( $handle );
                        $description=imagick_faileddescription( $handle );

                        print "imagick_writeimage() failed<BR>\nReason: $reason<BR>\nDescription: $description<BR>\n";
                    }
                    break;

                case 'IMAGICK_PECL2':
                    $image=new Imagick( $img_src );
                    if (false != $img_type) {
                    	if ('GrayScale' == $img_type)
                    		$image->setImageType(imagick::IMGTYPE_GRAYSCALE);
                    }
                    $image->thumbnailImage( $img_width, $img_height, 1 );
                     
                    $image->writeImage( $img_destination );
                    $img_attrb=$image->getImageGeometry();
                    $image->destroy();

                    $img_width=$img_attrb['width'];
                    $img_height=$img_attrb['height'];
                    break;

                case 'IMAGICK_SHELL':

                    $img_attrb=$this->image_info( $img_src );

										if ($img_stretch == 0 || $img_stretch=="") {
												if(($img_attrb['width'] <= $img_width) AND ($img_attrb['height'] <= $img_height)) 
												{
													$new_width=$img_attrb['width'];
													$new_height=$img_attrb['height'];
												} else {
														$dimensions = $this->getProportionalSize($img_attrb['width'],$img_attrb['height'],$img_width,$img_height);
														$new_width = $dimensions[0];
														$new_height = $dimensions[1];
												}
										} else {
													$new_width=$img_width;
													$new_height=$img_height;
										}
										if (false != $img_type) {
											$type='-type '.$img_type;
										} else {
											$type='';
										}
										
                    $out= system( "convert '" . $img_src . "' ".$type." -strip -geometry " . $new_width . "x" . $new_height . " "
                        . $img_destination . " ",
                            $retval );
                    $size=$this->image_quickinfo( $img_destination );
                    $img_width=$size['width'];
                    $img_height=$size['height'];
                    break;
                case 'MAGICKWAND':
										$resource = NewMagickWand();
										MagickReadImage( $resource, $img_src );
                    $img_attrb=$this->image_info( $img_src );

										if ($img_stretch == 0 || $img_stretch=="") {
												if(($img_attrb['width'] <= $img_width) AND ($img_attrb['height'] <= $img_height)) 
												{
													$new_width=$img_attrb['width'];
													$new_height=$img_attrb['height'];
												} else {
														$dimensions = $this->getProportionalSize($img_attrb['width'],$img_attrb['height'],$img_width,$img_height);
														$new_width = $dimensions[0];
														$new_height = $dimensions[1];
												}
										} else {
													$new_width=$img_width;
													$new_height=$img_height;
										}
										MagickProfileImage( $resource,'*');
										MagickResizeImage( $resource, $new_width, $new_height,  MW_BesselFilter, .5 );
										MagickSetImageCompressionQuality( $resource,$img_quality);
										MagickWriteImage($resource,$img_destination);
										$img_width = $new_width;
										$img_height = $new_height;
                    break;
                  case  'GD':
                  	
   									if ('jpg' == $img_end || 'jpeg' == $img_end) {
                  		$resource = imagecreatefromjpeg($img_src);
                  	} elseif('gif' == $img_end) {
                  		$resource = imagecreatefromgif($img_src);
                  	} else {
                  		print "unsupportet format ".$img_src."<br />";
                  		return;
                  	}
                  	$width = imagesx($resource);
                  	$height = imagesy($resource);

										if ($img_stretch == 0 || $img_stretch=="") {
												if(($width <= $img_width) AND ($height <= $img_height)) 
												{
													$new_width=$width;
													$new_height=$height;
												} else {
														$dimensions = $this->getProportionalSize($width,$height,$img_width,$img_height);
														$new_width = $dimensions[0];
														$new_height = $dimensions[1];
												}
										} else {
													$new_width=$img_width;
													$new_height=$img_height;
										}
                  	
                  	$image_p = ImageCreateTrueColor($new_width, $new_height);
			            	imagecopyresampled(
			                $image_p, $resource, 0, 0, 0, 0, $new_width, $new_height, $width, $height);

   									if ('jpg' == $img_end || 'jpeg' == $img_end) {
                  		imagejpeg($image_p, $img_destination, $img_quality);
                  	} elseif('gif' == $img_end) {
                  		imagegif($image_p, $img_destination);
                  	} 
                    $size=$this->image_quickinfo( $img_destination );
                    $img_width=$size['width'];
                    $img_height=$size['height'];                  
                  break;
                }

        }
        else
        {
            $size=$this->image_quickinfo( $img_destination );
            $img_width=$size['width'];
            $img_height=$size['height'];
        }


        return array
            (
            "src" => $this->config->get( 'WEB_ROOT' ) .$this->config->get( 'IMAGE_CACHE_DIR' ).$dir.'/'.$img_destfile,
            "width" => $img_width,
            "height" => $img_height
            );
    }

// -------------------------------------------------------------------------------------------------------------------
    function img_cache_show( $params, &$smarty=false )
    {
        $return="";

        if ( !isset( $params['src'] ) && !isset($params['img']) )
            $smarty->trigger_error( 'src or img array needed' );

				if ( !isset( $params['src'] ) && isset($params['img'] ) ) {
					$params['src'] = $this->config->get('MEDIA_WEB').$params['img']['picture_dir'].$params['img']['picture_filename'];
				}
				

        isset( $params['alt'] ) ? $img_alt=$params['alt'] : $img_alt="";
        isset( $params['width'] ) ? $img_width=$params['width'] : $img_width=$img_attrb['width'];
        isset( $params['height'] ) ? $img_height=$params['height'] : $img_height=$img_attrb['height'];
        isset( $params['stretch'] ) ? $stretch=$params['stretch'] : $stretch=0;
        isset( $params['quality'] ) ? $quality=$params['quality'] : $quality=90;
        isset( $params['border'] ) ? $border=$params['border'] : $border=0;
        isset( $params['title'] ) ? $title=$params['title'] : $title="";
        isset( $params['align'] ) ? $align=" align=\"" . $params['align'] . "\" " : $align="";
        isset( $params['id'] ) ? $img_id=$params['id'] : $img_id="rez_image_" . rand();
        isset( $params['style'] ) ? $style="style=\"" . $params['style'] . "\"" : $style="";

				$img_type = isset($params['type']) ? $params['type'] : false;

        if ( file_exists( $this->config->get( 'DOC_ROOT' ) . $this->config->get( 'WEB_ROOT' ) . $params['src'] ) )
        {
            $img_src=
                $this->img_cache_resize( $this->config->get( 'DOC_ROOT' ) . $this->config->get( 'WEB_ROOT' )
                    . $params['src'],
                    $img_width, $img_height, $stretch, $quality,$img_type );
            $return=
                "<img id=\"" . $img_id . "\" border=\"" . $border . "\" " . $align . " title=\"" . $title . "\" src=\""
                . $img_src['src'] . "\"  alt=\"" . $img_alt . "\" width=\"" . $img_src['width'] . "\" height=\""
                . $img_src['height'] . "\" " . $style . " />";
        }
        else
        {
//            trigger_error( 'Image cannot be found in: ' . $this->config->get( 'DOC_ROOT' )
//                . $this->config->get( 'WEB_ROOT' ) . $params['src'] );
        }

        return $return;
    }
// -------------------------------------------------------------------------------------------------------------------

    function img_cache_return_array( $params )
    {
        if ( !isset( $params['src'] ) && !isset($params['img']) )
            $smarty->trigger_error( 'src or img array needed' );

				if ( !isset( $params['src'] ) && isset($params['img'] ) ) {
					$params['src'] = $this->config->get('MEDIA_WEB').$params['img']['picture_dir'].$params['img']['picture_filename'];
				}

        $return=array();

        isset( $params['width'] ) ? $img_width=$params['width'] : $img_width=$img_attrb['width'];
        isset( $params['height'] ) ? $img_height=$params['height'] : $img_height=$img_attrb['height'];
        isset( $params['stretch'] ) ? $stretch=$params['stretch'] : $stretch=0;
        isset( $params['quality'] ) ? $quality=$params['quality'] : $quality=90;

				$img_type = isset($params['type']) ? $params['type'] : false;


        if ( file_exists( $this->config->get( 'DOC_ROOT' ) . $params['src'] ) )
        {
            $img_src=
                $this->img_cache_resize( $this->config->get( 'DOC_ROOT' ) . $params['src'], $img_width, $img_height,
                    $stretch, $quality,$img_type );
            $return["size"]=$img_size;
            $return["src"]=$img_src['src'];

            $return["width"]=$img_src['width'];
            $return["height"]=$img_src['height'];
        }
        else {

        //$smarty->trigger_error('Image cannot be found in: '.$this->config->get('DOC_ROOT').$params['src']);

        }
        return $return;
    }

// -------------------------------------------------------------------------------------------------------------------
    function img_cache_return( $params, &$smarty )
    {

        $return=$this->img_cache_return_array( $params );

        $smarty->assign( "img_" . $params['id'], $return );
    }

// -------------------------------------------------------------------------------------------------------------------
    function return_img_name( $params, &$smarty )
    {

        $img_src=$params['src'];
        $img_width=$params['width'];
        $img_height=$params['height'];

        list( $img_org, $img_end )=preg_split( "/\./", $img_src );

        if ( $img_end != 'jpg' && $img_end != 'jpeg' && $img_end != 'gif' && $img_end != 'png' )
        {
            $img_end='jpg';
        }

        $img_destfile=MD5( $img_src ) . "." . $img_width . "x" . $img_height . "." . $img_end;
        $img_destination=$this->config->get( 'IMAGE_CACHE_DIR' ) . $img_destfile;
        return $img_destination;
    }
// -------------------------------------------------------------------------------------------------------------------

    function crop( $img_src, $width, $height, $offsX, $offsY )
    {

        list( $img_org, $img_end )=preg_split( "/\./", $img_src );

        if ( $img_end != 'jpg' && $img_end != 'jpeg' && $img_end != 'gif' && $img_end != 'png' )
        {
            $img_end='jpg';
        }

        $img_destfile="ccds_cache/tmp/" . MD5( $img_src ) . '.' . $img_end;
        $img_destination=$this->config->get( 'DOC_ROOT' ) . $this->config->get( 'WEB_ROOT' ) . $img_destfile;
        $create_new=false;

        switch ( $this->engine )
            {
            case 'IMAGICK_PECL': break;

            case 'IMAGICK_PECL2':
                $image=new Imagick( $img_src );
                $imagick->rotateImage( new ImagickPixel(), $direction );
                $imagick->writeImage( $img_destination );
                break;

            case 'IMAGICK_SHELL':
                $out=
                    system( "convert '" . $img_src . "' -crop " . $width . "x" . $height . "+" . $offsX . "+" . $offsY
                        . " -strip " . $img_destination . " ",
                        $retval );
                $size=$this->image_info( $img_destination );
                $img_width=$size['img_width'];
                $img_height=$size['img_height'];
                break;
            }

        return $img_destfile;
    }

    function rotate( $img_src, $direction )
    {

        list( $img_org, $img_end )=preg_split( "/\./", $img_src );

        if ( $img_end != 'jpg' && $img_end != 'jpeg' && $img_end != 'gif' && $img_end != 'png' )
        {
            $img_end='jpg';
        }

        $img_destfile="ccds_cache/tmp/" . MD5( $img_src ) . '.' . $img_end;
        $img_destination=$this->config->get( 'DOC_ROOT' ) . $this->config->get( 'WEB_ROOT' ) . $img_destfile;
        $create_new=false;

        switch ( $this->engine )
            {
            case 'IMAGICK_PECL': break;

            case 'IMAGICK_PECL2':
                $image=new Imagick( $img_src );
                $imagick->rotateImage( new ImagickPixel(), $direction );
                $imagick->writeImage( $img_destination );
                break;

            case 'IMAGICK_SHELL':
                $out=
                    system( "convert '" . $img_src . "' -quality 100 -rotate " . $direction . " -strip "
                    . $img_destination . " ",
                        $retval );
                $size=$this->image_info( $img_destination );
                $img_width=$size['img_width'];
                $img_height=$size['img_height'];
                break;
            }

        return $img_destfile;
    }
}
